#ifndef CUSEDIT_EDIT_H
#define CUSEDIT_EDIT_H

#include <windows.h>
#include <vector>
#include <string>
#include <unordered_set>
#include <algorithm>
#include <memory>

#define IDC_GuiID 1001

namespace edit {

class Editor {
public:
    Editor();

    ~Editor();

    int Init(HINSTANCE hInstance, HWND parent);

    LRESULT CALLBACK runProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

    int initFontInfo();

public:
    void updateScrollBars(HWND hwnd);
    void paintWindow(HWND hwnd);
    void handleChar(HWND hwnd, WPARAM wParam);
    void handleKeyDown(HWND hwnd, WPARAM wParam);
    void updateCurosr(HWND hwnd);
    void drawTextLine(HDC hdc, int lineNum, int x, int y);
    void synataxHighlight(HDC hdc, const std::string& line, int x, int y);

private:
    HWND _hSelf = NULL;

    std::vector<std::string> lines_;
    int cursorX_ = 0;
    int cursorY_ = 0;
    int scrollX_ = 0;
    int scrollY_ = 0;
    int charWidth_ = 8;
    int charHeight_ = 16;
    bool cursorVisible_ = true;
    bool inCommentBlock_ = false;
    ULONGLONG lastBlink_ = 0;

    std::unordered_set<std::string> keywords_ = {
        "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor",
        "bool", "break", "case", "catch", "char", "char8_t", "char16_t", "char32_t",
        "class", "compl", "concept", "const", "consteval", "constexpr", "const_cast",
        "continue", "co_await", "co_return", "co_yield", "decltype", "default", "delete",
        "do", "double", "dynamic_cast", "else", "enum", "explicit", "export", "extern",
        "false", "float", "for", "friend", "goto", "if", "inline", "int", "long",
        "mutable", "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator",
        "or", "or_eq", "private", "protected", "public", "register", "reinterpret_cast",
        "return", "short", "signed", "sizeof", "static", "static_assert", "static_cast",
        "struct", "switch", "template", "this", "thread_local", "throw", "true", "try",
        "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
        "volatile", "wchar_t", "while", "xor", "xor_eq"
    };

    static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

    static constexpr wchar_t _className[32] = L"aeditor";
};

} // namespace edit

#endif // CUSEDIT_EDIT_H